﻿//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//    Crolengi, this program (a part of program) is gameengine based on C++\Directx
//    Copyright (C) 2008 Pashinin Anton Alekseevich (Crol)
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//    (INCLUDING NEGLIGENCE OR OTHERWISE) 
//    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
//    EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//    Contacts: 
//    Mail: crolengi@gmail.com
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


#ifndef  Console_h
#define  Console_h


#include "..\\import\\CRLEngi_strings_lib\\CRLEngi_strings.h"
#include "..\\import\\param_trees_lib\\param_trees.h"
//#include "include\\Managers\\TimeLine.h"
//#include "include\\Managers\\Event_Manager.h"
#include "include\\Utils\\Timer.h"

#include "include\\UI\\EditBox.h"
#include "include\\UI\\TextBox.h"
#include "include\\UI\\MLabel.h"


#ifdef	__cplusplus
extern "C" {
#endif

    #include "include\\lua\\lua_import\\lua.hpp"

#ifdef	__cplusplus
};
#endif


#include <windows.h>

//#################################################################################################################
///// 
/////   :: КЛАСС :: 
///// 
//#################################################################################################################
class CLREngi_Console
{
  protected:
	// A structure for our custom vertex type
	struct CUSTOMVERTEX
	{
		FLOAT x, y, z, rhw; // The transformed position for the vertex
		DWORD color;        // The vertex color
	};
	// Our custom FVF, which describes our custom vertex structure
    #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)

  protected:
    DynamicRow               LOG;
    int                      LOGid;
	Timer                    ConsoleTimer;          //global console time		
	//short                    limit_a,limit_b;
//	LPDIRECT3DVERTEXBUFFER9  g_pVB;
//	LPDIRECT3DVERTEXBUFFER9  g_pVB2;
//	LPDIRECT3DVERTEXBUFFER9  help_VB;
	LPDIRECT3DDEVICE9       *Device;
	//LPD3DXFONT               Font6Kartika; 
//	LPD3DXFONT               EnterFont;
	//LPD3DXFONT               BigFont;
	CRLEngi_string           CommandBuffer;
	D3DCOLOR                 BackColor;
	D3DCOLOR                 BackColor2;
	D3DCOLOR                 BackColor3;

	DynamicRow              *TimeLine;
	lua_State               *lua;
	///////////////////////// базы команд
	DynamicRow               GlobalCommandBase;
	DynamicRow               ConsoleCommandBase; // база введенных команд
	int                      ConsoleCommandBaseID;  

	//CLREngi_Event_Manager    *EventManager;
	///UI///
	CLREngi_UI_EditBox        *EditBox;
	CLREngi_UI_TextBox        *TextBox;
	CLREngi_UI_MLabel         *MLabel;
		
  public:
	Timer                    Timer02; // for "~"	
	Timer                    Timer01; //global console time	
	bool                     visible;
//#################################################################################################################
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void         Save(char *file){
	CRLEngi_string f;
	f=file;
	LOG.iSaveToFile(f);
	}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void         AddError(CRLEngi_string error){

	    int id;
	    id = LOG.AddToId(LOGid,true,error);
	    LOG.AddToId(id,false,"_ERROR_");	  
	    }

void         AddText(CRLEngi_string text,short err){
        CRLEngi_string buffer;
		buffer ="[";
		buffer += (int)(ConsoleTimer.getElapsedTimeMilliSeconds()/1000);
		buffer +=":";
		int milli = (int)(ConsoleTimer.getElapsedTimeMilliSeconds()%1000);
		if (milli<10) 
			milli=milli*100;
		if (milli<100)
			milli=milli*10;
		buffer +=milli;
		buffer +="] ";

		buffer +=text;

		int id;
		char buffer2[1024];
		char buffer2_2[1024]; int j=0; int fif=85;
		strcpy(buffer2,buffer.getChars());
		while (true){
		 if (strlen(buffer2)<85)
		 {
			 id = LOG.AddToId(LOGid,true,buffer);
			 if(err==1){
				 LOG.AddToId(id,false,"_ERROR_");	 
			     Save("MAIN_LOG");
			 }
		     else if(err==0)
	            LOG.AddToId(id,false,"_TEXT_");	  
		     else if(err==2)
	            LOG.AddToId(id,false,"_COMMENT_");	 
		     else if(err==3)
	            LOG.AddToId(id,false,"_SYSTEM_");
			 break;		 
		 }
		 for (int i=0;i<=strlen(buffer2);i++){
		     buffer2_2[j] = buffer2[i];
			 buffer2_2[j+1] = '\0';
			 j++;
			 if ((i==fif)||(i==strlen(buffer2))){
				 id = LOG.AddToId(LOGid,true,buffer2_2);
				 if(err==1){
		           LOG.AddToId(id,false,"_ERROR_");	 
				   Save("MAIN_LOG");
				 }
		         else if(err==0)
	               LOG.AddToId(id,false,"_TEXT_");	  
		         else if(err==2)
	               LOG.AddToId(id,false,"_COMMENT_");	 
		         else if(err==3)
	               LOG.AddToId(id,false,"_SYSTEM_");			    
				 fif+=85; 
				 buffer2_2[0]=' ';
				 buffer2_2[1]=' ';
				 buffer2_2[2]=' ';
				 j=3;
			    }
		    }
		  break;	
		 }/*

		buffer += buffer2;
		
	    
	    id = LOG.AddToId(LOGid,true,buffer);
		if(err==1)
		LOG.AddToId(id,false,"_ERROR_");	 
		else if(err==0)
	    LOG.AddToId(id,false,"_TEXT_");	  
		else if(err==2)
	    LOG.AddToId(id,false,"_COMMENT_");	 
		else if(err==3)
	    LOG.AddToId(id,false,"_SYSTEM_");	*/
	    }
void         AddText(char *ch,short er){

		CRLEngi_string text;
		text = ch;
		AddText(text,er);
		}
void         AddText(char *ch){

		CRLEngi_string text;
		text = ch;
		AddText(text,false);
		}
void         AddText(CRLEngi_string text){

         AddText(text,false);
		}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void         DrawText(CRLEngi_string text,int pos_x,int pos_y,D3DCOLOR color){
		RECT destRect;
		SetRect( &destRect, pos_x, pos_y, 0, 0 ); 
	//	Font6Kartika->DrawText( NULL,text.getChars(), -1, &destRect, DT_NOCLIP, color );
	}//void
void         DrawTextBold(CRLEngi_string text,int pos_x,int pos_y,D3DCOLOR color){
		RECT destRect;
		char *buffer00;
		char buffer01[41];
		buffer00 = text.getChars();
		int len = strlen(buffer00);
		  
		  if (len>30){
			
		    int j = 0;

			for (int i=30;i>=0;i--){
				buffer01[j] = buffer00[len-i+1];
				buffer01[j+1]='\0';
				j++;
			}
		  SetRect( &destRect, pos_x, pos_y, 0, 0 ); 
		//  EnterFont->DrawText( NULL,buffer01, -1, &destRect, DT_NOCLIP, color );
		}
		else{
		   SetRect( &destRect, pos_x, pos_y, 0, 0 ); 
		//  EnterFont->DrawText( NULL,text.getChars(), -1, &destRect, DT_NOCLIP, color );
		}
	}//void

void         DrawError(CRLEngi_string text,int pos_x,int pos_y,D3DCOLOR color){
		RECT destRect;
		SetRect( &destRect, pos_x, pos_y, 0, 0 ); 
		//Font6Kartika->DrawText( NULL,text.getChars(), -1, &destRect, DT_NOCLIP,color);
	}//void
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void         Hide_unHide(){
  
	  if(visible == false){
			   visible = true;
			   ConsoleTimer.iStop();
	          }
	  else {
		       visible = false; 
			   ConsoleTimer.iResume();
	          }
  
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int          GetCurrientTime_seconds(){
       return (int)(ConsoleTimer.getElapsedTimeMilliSeconds()/1000);
}
int          GetCurrientTime_mseconds(){
       return (int)(ConsoleTimer.getElapsedTimeMilliSeconds());
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void         AnalyzeCommand(char  *Cm){
CRLEngi_string  Command;
 Command = Cm;
 AnalyzeCommand( Command);
}
void         AnalyzeCommand(CRLEngi_string  Command){

	if (!(Command=="")){
      /// теперь анализ команды
	  CRLEngi_string  C1,C2;
	  Command.NoTabs();
	  Command.DivideTwoParameters(&C1,&C2);	
	   if (C1=="hide"){
		   AddText(Command,0);
		   visible = false;
	       }
	   else 
	  if(C1=="save"){
		  AddText(Command,0);
		  Save(C2.getChars());
          AddText("Save completed");
	      }
	   else 
	  if(C1=="clr"){
		    AddText(Command,0);
            LOG.fresh();
	        LOGid = LOG.AddToId(0,true,"LOG");
	        }
	  else
	  {
		  (*TimeLine).AddToId(1,false,Command);
		  AddText(Command,2);
	  }
	  
	 }
}//void


void         getKeyCommands(LPSTR lpstr,bool state){
  if ((EditBox->console_close_needed)&&(!state))  
  {
	  visible = false; 
	  ConsoleTimer.iResume();
	  EditBox->console_close_needed = false;
  }
  else{
	unsigned char keys[256];
    GetKeyboardState( keys );

    EditBox->KeyEvent(keys,lpstr,state);

	
  }

}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void         Draw(){	
			if(visible){											
				(*Device)->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
				TextBox->Render();	
				EditBox->Render();
				MLabel->Render();
				
				if (ConsoleTimer.getElapsedTimeMilliSeconds()%1000>0){
				CRLEngi_string b;
				b.clear();
		         b ="[";
		         b += (int)(ConsoleTimer.getElapsedTimeMilliSeconds()/1000);
		         b +=":";
		         int milli = (int)(ConsoleTimer.getElapsedTimeMilliSeconds()%1000);
		         if (milli<10) 
			         milli=milli*100;
		         if (milli<100)
			         milli=milli*10;
		         b +=milli;
		           b +="] ";
				DrawText(b,560,62,D3DCOLOR_XRGB(250,250,250));
				MLabel->SetText(b.getChars());

				}}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT      Init(){
	

	/// очистка таймеров
	Timer01.getCurrentTime();
	ConsoleTimer.intialize();

	ConsoleTimer.getCurrentTime();
	Timer02.intialize();
	Timer02.getCurrentTime();

	//настройка списков команд
	GlobalCommandBase.fresh();
	CRLEngi_string file;
	file = "GlobalCommandBase.DR";
	GlobalCommandBase.iLoadFromFile(file);	
	ConsoleCommandBase.fresh();
	ConsoleCommandBase.AddToId(0,true,"_COMMANDS_");
	ConsoleCommandBaseID = 0;

	BackColor2   = D3DCOLOR_XRGB(10,10,10);
	BackColor    = D3DCOLOR_XRGB(34,34,34);
	BackColor3   = D3DCOLOR_XRGB(54,54,54);


////////////////////////////////////////////////////
		SYSTEMTIME st;
		CRLEngi_string  DATE; 
        GetSystemTime(&st);             
	    char timedate[40];
		DATE = "[Currient date: ";

		DATE+=st.wDay;DATE+="-";
		DATE+=st.wMonth;DATE+="-";
		DATE+=st.wYear;DATE+=" ";

		DATE+=st.wYear;DATE+=" , time: ";

		DATE+=st.wHour;DATE+="-";
		DATE+=st.wMinute;DATE+="-";
		DATE+=st.wSecond;DATE+=" (GMT+0)";
		DATE += "]";

		int id = LOG.AddToId(LOGid,true,DATE);
		LOG.AddToId(id,false,"_SYSTEM_");
		return true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void         KeyTimersAreReady(){
	Timer01.lastTime+=100000;	
	Timer02.lastTime+=100000;	
	EditBox->InputTimer.lastTime+=100000;	
	}
void         KeyTimersUpdate(){
	Timer01.getCurrentTime();	
	Timer02.getCurrentTime();
	EditBox->InputTimer.getCurrentTime();
	}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void         SetTimeLine(DynamicRow   *TL){
 TimeLine  = TL;
 EditBox->TimeLine = TimeLine;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void         MouseInput(unsigned short event_index,POINT m){
	if(visible){
		/*if(!EditBox->MouseEvent(event_index,m))
		TextBox->MouseEvent(event_index,m);
		else 
		{TextBox->Deselect();}*/
            //MLabel

		if(!MLabel->MouseEvent(event_index,m))
		if(!EditBox->MouseEvent(event_index,m))
		    TextBox->MouseEvent(event_index,m);

	}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// отправка команд в луа, находится тут потому что доступ к консоли обеспечен всем объектам
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int          Lua_SendCommand(CRLEngi_string *ObjectName,CRLEngi_string *Event){
   /* lua_pcall       ( lua, 0, LUA_MULTRET, 0 );
    lua_getfield    ( lua, LUA_GLOBALSINDEX, "EventToLua" );   // push global function f on stack
    lua_pushstring  ( lua, (*ObjectName).getChars() );                      // push first argument on stack
	lua_pushstring  ( lua, (*Event).getChars() );                      // push first argument on stack
    lua_pcall       ( lua, 2, 1, 0 );                   // call function taking 2 argsuments and getting one return value
	return lua_tointeger ( lua, -1 );*/

	lua_pcall       ( lua, 0, LUA_MULTRET, 0 );
	lua_getfield    ( lua, LUA_GLOBALSINDEX, "EventToLua" );   // push global function f on stack
    lua_pushstring  ( lua, (*ObjectName).getChars() );                      // push first argument on stack
	lua_pushstring  ( lua, (*Event).getChars() );                      // push first argument on stack
    lua_pcall       ( lua, 2, 1, 0 );                   // call function taking 2 argsuments and getting one return value
    
    
	return lua_tointeger ( lua, -1 );

}

bool         Lua_Open_Script(CRLEngi_string *FName){
  if(luaL_dofile(lua,(*FName).getChars())){
	  char a[1024];
      strcpy(a,(lua_tostring( lua, -1 )));
	  AddText(".lua not loaded ! in cause of:",1);
	  AddText(a,1);
	  return false;
   }
 else{
	 AddText("[+]  script",1);
 return true;
 }
}

void         setScriptSource(lua_State *lu){
lua = lu;
}

//#################################################################################################################
CLREngi_Console(LPDIRECT3DDEVICE9 *D){
   LOG.fresh();
   LOGid = LOG.AddToId(0,true,"LOG");
   visible = false;

   Device=D;
   Init();
   TimeLine = NULL;
   EditBox = new CLREngi_UI_EditBox(Device,TimeLine,"Ввод команды:");
   EditBox->Setup(9,200,415,400,D3DCOLOR_XRGB(250,250,250));
   EditBox->Select();

   TextBox = new CLREngi_UI_TextBox(Device,&LOG,"команды:");
   //TextBox->Setup(9,30,515,150,D3DCOLOR_XRGB(150,150,150));
   TextBox->Setup(9,30,580,150,D3DCOLOR_XRGB(250,250,250));


   MLabel = new CLREngi_UI_MLabel(Device,"Текущее время");
   MLabel->Setup_SizePos(657,200,80,17);


  
   
   }

~CLREngi_Console(void)
   {
       GlobalCommandBase.fresh();
	   ConsoleCommandBase.fresh();
	   LOG.fresh();
	   EditBox->~CLREngi_UI_EditBox();
       TextBox->~CLREngi_UI_TextBox();
   }

};
//#################################################################################################################
#endif 